package leetcode.dynamic;

/**
 * 给你一个字符串 s ，找出其中最长的回文子序列，并返回该序列的长度。
 * <p>
 * 子序列定义为：不改变剩余字符顺序的情况下，删除某些字符或者不删除任何字符形成的一个序列。
 * <p>
 * <p>
 * <p>
 * 示例 1：
 * <p>
 * 输入：s = "bbbab"
 * 输出：4
 * 解释：一个可能的最长回文子序列为 "bbbb" 。
 * 示例 2：
 * <p>
 * 输入：s = "cbbd"
 * 输出：2
 * 解释：一个可能的最长回文子序列为 "bb" 。
 * <p>
 * <p>
 * 提示：
 * <p>
 * 1 <= s.length <= 1000
 * s 仅由小写英文字母组成
 */
public class LeetCode516_LongestPalindromeSubseq {
    public int longestPalindromeSubseq(String s) {
        return f(s.toCharArray(), 0, s.length() - 1);
    }

    public int f(char[] s, int i, int j) {
        if (i + 1 == j) {
            return s[i] == s[j] ? 2 : 1;
        }

        if (i == j) {
            return 1;
        }
        if (s[i] == s[j]) {
            return f(s, i + 1, j - 1) + 2;
        } else {
            return Math.max(f(s, i + 1, j), f(s, i, j - 1));
        }
    }

    public int longestPalindromeSubseq2(String s) {
        char[] arr = s.toCharArray();
        int[][] dp = new int[arr.length][arr.length];

        for (int i = arr.length - 1; i >= 0; i--) {
            for (int j = i; j < arr.length; j++) {
                if (i == j) {
                    dp[i][j] = 1;
                    continue;
                }
                if (i + 1 == j) {
                    dp[i][j] = arr[i] == arr[j] ? 2 : 1;
                } else {
                    if (arr[i] == arr[j]) {
                        dp[i][j] = dp[i + 1][j - 1] + 2;
                    } else {
                        dp[i][j] = Math.max(dp[i + 1][j], dp[i][j - 1]);
                    }
                }
            }
        }
        return dp[0][arr.length - 1];
    }
}
